package com.aabte.permissionframeworklearn.permission.service;

import com.aabte.permissionframeworklearn.permission.dto.AclDto;
import com.aabte.permissionframeworklearn.permission.dto.AclModuleLevelDto;
import com.aabte.permissionframeworklearn.permission.dto.DeptLevelDto;
import com.aabte.permissionframeworklearn.permission.mapper.SysAclMapper;
import com.aabte.permissionframeworklearn.permission.mapper.SysAclModuleMapper;
import com.aabte.permissionframeworklearn.permission.mapper.SysDeptMapper;
import com.aabte.permissionframeworklearn.permission.model.SysAcl;
import com.aabte.permissionframeworklearn.permission.model.SysAclModule;
import com.aabte.permissionframeworklearn.permission.model.SysDept;
import com.aabte.permissionframeworklearn.permission.util.LevelUtil;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author Daniel
 */
@Service
public class SysTreeService {

    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private SysAclModuleMapper sysAclModuleMapper;

    @Autowired
    private SysAclMapper sysAclMapper;

    @Autowired
    private SysCoreService sysCoreService;

    public List<AclModuleLevelDto> roleTree(Long roleId) {
        // 1. 当前用户已分配的权限点
        List<SysAcl> currentUserAclList = sysCoreService.getCurrentUserAclList();

        // 2. 当前角色分配的权限点
        List<SysAcl> roleAclList = sysCoreService.getRoleAclList(roleId);

        // 3. 当前系统所有权限点
        List<SysAcl> allAcl = sysAclMapper.getAll();

        Set<Long> userAclIdList = currentUserAclList.stream()
                .map(SysAcl::getId).collect(Collectors.toSet());
        Set<Long> roleAclIdList = roleAclList.stream()
                .map(SysAcl::getId).collect(Collectors.toSet());

        // 4. 设置是否默认选中、是否有权限操作
        List<AclDto> aclDtoList = Lists.newArrayList();
        for (SysAcl sysAcl : allAcl) {
            AclDto dto = AclDto.adapt(sysAcl);
            if (userAclIdList.contains(sysAcl.getId())) {
                dto.setHasAcl(true);
            }
            if (roleAclIdList.contains(sysAcl.getId())) {
                dto.setChecked(true);
            }
            aclDtoList.add(dto);
        }

        return aclListToTree(aclDtoList);
    }

    public List<AclModuleLevelDto> aclListToTree(List<AclDto> aclDtoList) {
        if (CollectionUtils.isEmpty(aclDtoList)) {
            return Lists.newArrayList();
        }

        List<AclModuleLevelDto> aclModuleLevelDtoList = aclModuleTree();

        Multimap<Long, AclDto> aclDtoMultimap = ArrayListMultimap.create();
        for (AclDto dto : aclDtoList) {
            if (dto.getStatus() == 1) {
                aclDtoMultimap.put(dto.getAclModuleId(), dto);
            }
        }
        bindAclsWithOrder(aclModuleLevelDtoList, aclDtoMultimap);
        return aclModuleLevelDtoList;
    }

    public void bindAclsWithOrder(List<AclModuleLevelDto> aclModuleLevelDtoList, Multimap<Long, AclDto> aclDtoMultimap) {
        if (CollectionUtils.isEmpty(aclModuleLevelDtoList)) {
            return;
        }

        for (AclModuleLevelDto aclModuleLevelDto : aclModuleLevelDtoList) {
            List<AclDto> aclDtos = (List<AclDto>) aclDtoMultimap.get(aclModuleLevelDto.getId());
            if (CollectionUtils.isNotEmpty(aclDtos)) {
                aclDtos.sort(Comparator.comparing(AclDto::getSeq));
                aclModuleLevelDto.setAclList(aclDtos);
            }
            bindAclsWithOrder(aclModuleLevelDto.getAclModuleList(), aclDtoMultimap);
        }

    }


    public List<DeptLevelDto> deptTree() {
        List<SysDept> allDept = sysDeptMapper.getAllDept();
        List<DeptLevelDto> deptLevelDtos = generateDeptTree(allDept, LevelUtil.ROOT);
        return deptLevelDtos;
    }

    public List<DeptLevelDto> generateDeptTree(List<SysDept> allDept, String rootLevel) {
        List<DeptLevelDto> dtos = Lists.newArrayList();

        for (SysDept sysDept : allDept) {
            DeptLevelDto dto = DeptLevelDto.adapt(sysDept);
            dtos.add(dto);
        }
        return deptLevleDtosToTree(dtos, rootLevel);
    }

    public List<AclModuleLevelDto> aclModuleTree() {
        List<SysAclModule> sysAclModules = sysAclModuleMapper.getAllAclModule();
        List<AclModuleLevelDto> aclModuleTree = generateAclModuleTree(sysAclModules, LevelUtil.ROOT);
        return aclModuleTree;
    }

    public List<AclModuleLevelDto> userAclTree(Long userId) {

        List<SysAcl> currentUserAclList = sysCoreService.getUserAclList(userId);

        List<AclDto> aclDtoList = Lists.newArrayList();
        for (SysAcl sysAcl : currentUserAclList) {
            AclDto aclDto = AclDto.adapt(sysAcl);
            aclDtoList.add(aclDto);
        }
        return aclListToTree(aclDtoList);
    }

    public List<AclModuleLevelDto> generateAclModuleTree(List<SysAclModule> allDept, String rootLevel) {
        List<AclModuleLevelDto> dtos = Lists.newArrayList();

        for (SysAclModule sysDept : allDept) {
            AclModuleLevelDto dto = AclModuleLevelDto.adapt(sysDept);
            dtos.add(dto);
        }
        return aclModuleDtosToTree(dtos, rootLevel);
    }

    private List<AclModuleLevelDto> aclModuleDtosToTree(List<AclModuleLevelDto> dtos, String rootLevel) {
        if (CollectionUtils.isEmpty(dtos)) {
            return Lists.newArrayList();
        }

        Multimap<String, AclModuleLevelDto> levelDtoMulimap = ArrayListMultimap.create();
        List<AclModuleLevelDto> rootList = Lists.newArrayList();

        for (AclModuleLevelDto dto : dtos) {
            levelDtoMulimap.put(dto.getLevel(), dto);
            if (StringUtils.equals(rootLevel, dto.getLevel())) {
                rootList.add(dto);
            }
        }
        rootList.sort(Comparator.comparing(AclModuleLevelDto::getSeq));
        transformAclModuleTree(rootList, LevelUtil.ROOT, levelDtoMulimap);

        return rootList;
    }

    private void transformAclModuleTree(List<AclModuleLevelDto> rootList, String currentLevel, Multimap<String, AclModuleLevelDto> levelDtoMulimap) {
        for (AclModuleLevelDto aclModuleLevelDto : rootList) {
            String nextLevel = LevelUtil.calculateLevel(currentLevel, aclModuleLevelDto.getId());
            List<AclModuleLevelDto> aclModuleLevelDtos = (List<AclModuleLevelDto>) levelDtoMulimap.get(nextLevel);
            if (CollectionUtils.isNotEmpty(aclModuleLevelDtos)) {
                aclModuleLevelDtos.sort(Comparator.comparing(AclModuleLevelDto::getSeq));
                aclModuleLevelDto.setAclModuleList(aclModuleLevelDtos);
                transformAclModuleTree(aclModuleLevelDtos, nextLevel, levelDtoMulimap);
            }
        }
    }

    private List<DeptLevelDto> deptLevleDtosToTree(List<DeptLevelDto> deptLevelDtos, String rootLevel) {
        if (CollectionUtils.isEmpty(deptLevelDtos)) {
            return Lists.newArrayList();
        }

        Multimap<String, DeptLevelDto> levelDeptMultimap = ArrayListMultimap.create();
        List<DeptLevelDto> rootList = Lists.newArrayList();
        for (DeptLevelDto deptLevelDto : deptLevelDtos) {
            levelDeptMultimap.put(deptLevelDto.getLevel(), deptLevelDto);
            if (StringUtils.equals(rootLevel, deptLevelDto.getLevel())) {
                rootList.add(deptLevelDto);
            }
        }
        // 递归生成树
        rootList.sort(Comparator.comparing(DeptLevelDto::getSeq));
        transformDeptTree(rootList, LevelUtil.ROOT, levelDeptMultimap);
        return rootList;
    }

    private void transformDeptTree(List<DeptLevelDto> deptLevelDtos, String level, Multimap<String, DeptLevelDto> levelDeptMultimap) {
        for (DeptLevelDto deptLevelDto : deptLevelDtos) {
            // 遍历该层的每个元素
            // 处理当前层级的数据
            String nextLevel = LevelUtil.calculateLevel(level, deptLevelDto.getId());
            // 处理下一层
            List<DeptLevelDto> tempDeptLevelDtos = (List<DeptLevelDto>) levelDeptMultimap.get(nextLevel);
            if (CollectionUtils.isNotEmpty(tempDeptLevelDtos)) {
                // 排序
                tempDeptLevelDtos.sort(Comparator.comparing(DeptLevelDto::getSeq));
                // 设置下一层部门
                deptLevelDto.setDeptList(tempDeptLevelDtos);
                // 进入到下一层处理
                transformDeptTree(tempDeptLevelDtos, nextLevel, levelDeptMultimap);
            }
        }
    }
}
